namespace GemBox.Spreadsheet
{
    using System;
    using System.Data;
    using System.Data.Common;
    using System.Runtime.CompilerServices;

    public sealed class ExcelWorksheet
    {
        internal double bottomMargin;
        private CellRange cells;
        private ExcelColumnCollection columns;
        private int defaultColumnWidth;
        internal int firstVisibleColumn;
        internal int firstVisibleRow;
        internal ushort fitWorksheetHeightToPages;
        internal ushort fitWorksheetWidthToPages;
        internal double footerMargin;
        internal double headerMargin;
        internal HorizontalPageBreakCollection horizontalPageBreaks;
        private SpreadsheetHyperlinkCollection hyperlinks;
        internal double leftMargin;
        private MergedCellRanges mergedRanges;
        private string name;
        private NamedRangeCollection namedRanges;
        internal ushort numberOfCopies;
        internal int pageBreakViewZoom;
        internal ushort paperSize;
        private ExcelWorksheetCollection parent;
        private ExcelPictureCollection pictures;
        internal PreservedRecords PreservedWorksheetRecords;
        private ExcelPrintOptions printOptions;
        internal ushort printResolution;
        private bool protectedWorksheet;
        internal double rightMargin;
        private ExcelRowCollection rows;
        internal int scalingFactor;
        internal SetupOptions setupOptions;
        private ExcelShapeCollection shapes;
        internal ushort startPageNumber;
        internal object Tag;
        internal double topMargin;
        internal VerticalPageBreakCollection verticalPageBreaks;
        internal ushort verticalPrintResolution;
        private ExcelViewOptions viewOptions;
        internal WorksheetWindowOptions windowOptions;
        internal WSBoolOptions WSBoolOpt;
        internal int zoom;

        public event ExtractDataEventHandler ExtractDataEvent;

        internal ExcelWorksheet(string name, ExcelWorksheetCollection parent)
        {
            this.defaultColumnWidth = 0x924;
            this.pageBreakViewZoom = 60;
            this.zoom = 100;
            this.windowOptions = WorksheetWindowOptions.ShowOutlineSymbols | WorksheetWindowOptions.DefaultGridLineColor | WorksheetWindowOptions.ShowGridLines | WorksheetWindowOptions.ShowZeroValues | WorksheetWindowOptions.ShowSheetHeaders;
            this.scalingFactor = 100;
            this.startPageNumber = 1;
            this.setupOptions = SetupOptions.Portrait;
            this.headerMargin = 0.5;
            this.footerMargin = 0.5;
            this.topMargin = 1.9;
            this.bottomMargin = 1.9;
            this.leftMargin = 1.8;
            this.rightMargin = 1.8;
            this.numberOfCopies = 1;
            this.WSBoolOpt = WSBoolOptions.ShowRowOutline | WSBoolOptions.ShowColumnOutline | WSBoolOptions.ColGroupRight | WSBoolOptions.ShowAutoBreaks | WSBoolOptions.RowGroupBelow;
            this.name = name;
            this.parent = parent;
            this.rows = new ExcelRowCollection(this);
            this.columns = new ExcelColumnCollection(this);
            this.mergedRanges = new MergedCellRanges(this);
            this.horizontalPageBreaks = new HorizontalPageBreakCollection();
            this.verticalPageBreaks = new VerticalPageBreakCollection();
            this.pictures = new ExcelPictureCollection(this);
            this.shapes = new ExcelShapeCollection(this);
            this.printOptions = new ExcelPrintOptions(this);
            this.viewOptions = new ExcelViewOptions(this);
            this.hyperlinks = new SpreadsheetHyperlinkCollection(this);
        }

        internal ExcelWorksheet(string name, ExcelWorksheetCollection parent, ExcelWorksheet sourceWorksheet)
        {
            this.defaultColumnWidth = 0x924;
            this.pageBreakViewZoom = 60;
            this.zoom = 100;
            this.windowOptions = WorksheetWindowOptions.ShowOutlineSymbols | WorksheetWindowOptions.DefaultGridLineColor | WorksheetWindowOptions.ShowGridLines | WorksheetWindowOptions.ShowZeroValues | WorksheetWindowOptions.ShowSheetHeaders;
            this.scalingFactor = 100;
            this.startPageNumber = 1;
            this.setupOptions = SetupOptions.Portrait;
            this.headerMargin = 0.5;
            this.footerMargin = 0.5;
            this.topMargin = 1.9;
            this.bottomMargin = 1.9;
            this.leftMargin = 1.8;
            this.rightMargin = 1.8;
            this.numberOfCopies = 1;
            this.WSBoolOpt = WSBoolOptions.ShowRowOutline | WSBoolOptions.ShowColumnOutline | WSBoolOptions.ColGroupRight | WSBoolOptions.ShowAutoBreaks | WSBoolOptions.RowGroupBelow;
            this.name = name;
            this.parent = parent;
            this.protectedWorksheet = sourceWorksheet.protectedWorksheet;
            this.rows = new ExcelRowCollection(this, sourceWorksheet.rows);
            this.columns = new ExcelColumnCollection(this, sourceWorksheet.columns);
            this.defaultColumnWidth = sourceWorksheet.defaultColumnWidth;
            this.mergedRanges = new MergedCellRanges(this, sourceWorksheet.mergedRanges);
            this.WSBoolOpt = sourceWorksheet.WSBoolOpt;
            if (sourceWorksheet.PreservedWorksheetRecords != null)
            {
                this.PreservedWorksheetRecords = new PreservedRecords(sourceWorksheet.PreservedWorksheetRecords);
            }
            this.windowOptions = (WorksheetWindowOptions) ((ushort) (((int) sourceWorksheet.windowOptions) & 0xf9ff));
            this.firstVisibleRow = sourceWorksheet.firstVisibleRow;
            this.firstVisibleColumn = sourceWorksheet.firstVisibleColumn;
            this.pageBreakViewZoom = sourceWorksheet.pageBreakViewZoom;
            this.zoom = sourceWorksheet.zoom;
            this.horizontalPageBreaks = new HorizontalPageBreakCollection(sourceWorksheet.horizontalPageBreaks);
            this.verticalPageBreaks = new VerticalPageBreakCollection(sourceWorksheet.verticalPageBreaks);
            this.paperSize = sourceWorksheet.paperSize;
            this.scalingFactor = sourceWorksheet.scalingFactor;
            this.startPageNumber = sourceWorksheet.startPageNumber;
            this.fitWorksheetWidthToPages = sourceWorksheet.fitWorksheetWidthToPages;
            this.fitWorksheetHeightToPages = sourceWorksheet.fitWorksheetHeightToPages;
            this.setupOptions = sourceWorksheet.setupOptions;
            this.printResolution = sourceWorksheet.printResolution;
            this.verticalPrintResolution = sourceWorksheet.verticalPrintResolution;
            this.headerMargin = sourceWorksheet.headerMargin;
            this.footerMargin = sourceWorksheet.footerMargin;
            this.numberOfCopies = sourceWorksheet.numberOfCopies;
            this.namedRanges = new NamedRangeCollection(this, sourceWorksheet.NamedRanges);
            this.pictures = new ExcelPictureCollection(this, sourceWorksheet.Pictures);
            this.shapes = new ExcelShapeCollection(this, sourceWorksheet.Shapes);
            this.printOptions = new ExcelPrintOptions(this);
            this.viewOptions = new ExcelViewOptions(this);
            this.hyperlinks = new SpreadsheetHyperlinkCollection(this, sourceWorksheet.Hyperlinks);
            this.Tag = sourceWorksheet.Tag;
        }

        public void Delete()
        {
            this.parent.DeleteInternal(this);
        }

        public void ExtractToDataTable(DataTable dataTable, int numberOfRows, ExtractDataOptions options, ExcelRow startRow, ExcelColumn startColumn)
        {
            DataColumnMappingCollection dataColumnMappingCollection = new DataColumnMappingCollection();
            int index = startColumn.Index;
            if ((startColumn.Index + dataTable.Columns.Count) > 0x4000)
            {
                int num3 = 0x4000;
                throw new SpreadsheetException("Maximum nuber of columns is " + num3.ToString() + ".");
            }
            int num = 0;
            while (num < dataTable.Columns.Count)
            {
                dataColumnMappingCollection.Add(ExcelColumnCollection.ColumnIndexToName(index), dataTable.Columns[num].ColumnName);
                num++;
                index++;
            }
            this.ExtractToDataTable(dataTable, numberOfRows, options, dataColumnMappingCollection, startRow);
        }

        public void ExtractToDataTable(DataTable dataTable, int numberOfRows, ExtractDataOptions options, DataColumnMappingCollection dataColumnMappingCollection, ExcelRow startRow)
        {
            int index = 0;
            int[] numArray = new int[dataColumnMappingCollection.Count];
            if ((startRow.Index + numberOfRows) > 0x100000)
            {
                int num4 = 0x100000;
                throw new SpreadsheetException("Maximum number of rows exceeded. Maximum number of rows is " + num4.ToString() + ".");
            }
            foreach (DataColumnMapping mapping in dataColumnMappingCollection)
            {
                numArray[index] = ExcelColumnCollection.ColumnNameToIndex(mapping.SourceColumn);
                index++;
            }
            for (int i = startRow.Index; i < (startRow.Index + numberOfRows); i++)
            {
                bool flag = false;
                bool flag2 = false;
                DataRow row = dataTable.NewRow();
                int num2 = 0;
                for (index = 0; index < dataColumnMappingCollection.Count; index++)
                {
                    DataColumnMapping columnMapping = dataColumnMappingCollection[index];
                    object excelValue = null;
                    if (i < this.rows.Count)
                    {
                        ExcelCellCollection allocatedCells = this.rows[i].AllocatedCells;
                        if (numArray[index] < allocatedCells.Count)
                        {
                            excelValue = allocatedCells[numArray[index]].Value;
                        }
                    }
                    bool flag3 = ValueCanConvertToDataTableType(dataTable.Columns[columnMapping.DataSetColumn].DataType, excelValue);
                    if (flag3)
                    {
                        if (excelValue == null)
                        {
                            num2++;
                        }
                        try
                        {
                            row[columnMapping.DataSetColumn] = excelValue;
                        }
                        catch (InvalidCastException)
                        {
                            flag3 = false;
                        }
                    }
                    if (!flag3)
                    {
                        ExtractDataDelegateEventArgs args = this.OnWrongDataType(columnMapping, this.Rows[i], dataTable, excelValue);
                        if (args.Action == ExtractDataEventAction.Continue)
                        {
                            try
                            {
                                row[columnMapping.DataSetColumn] = args.DataTableValue;
                                goto Label_01C1;
                            }
                            catch (InvalidCastException exception)
                            {
                                ThrowInvalidDataException(i, numArray[index], exception);
                                goto Label_01C1;
                            }
                        }
                        if (args.Action == ExtractDataEventAction.ThrowException)
                        {
                            ThrowInvalidDataException(i, numArray[index], null);
                        }
                        else
                        {
                            if (args.Action == ExtractDataEventAction.StopReading)
                            {
                                flag2 = true;
                                break;
                            }
                            if (args.Action == ExtractDataEventAction.SkipRow)
                            {
                                flag = true;
                                break;
                            }
                        }
                    Label_01C1:;
                    }
                }
                if (flag2)
                {
                    return;
                }
                if (!flag)
                {
                    if ((num2 == dataTable.Columns.Count) && ((options & ExtractDataOptions.StopAtFirstEmptyRow) != ExtractDataOptions.None))
                    {
                        return;
                    }
                    dataTable.Rows.Add(row);
                }
            }
        }

        public CellRange GetUsedCellRange()
        {
            int count = 0;
            foreach (ExcelRow row in this.Rows)
            {
                if (row.AllocatedCells.Count > count)
                {
                    count = row.AllocatedCells.Count;
                }
            }
            if (count > 0)
            {
                return new CellRange(this, 0, 0, this.Rows.Count - 1, count - 1);
            }
            return null;
        }

        internal bool GetWindowOption(WorksheetWindowOptions option)
        {
            return Utilities.IsBitSet((ushort) this.windowOptions, (ushort) option);
        }

        internal bool GetWSBoolOption(WSBoolOptions option)
        {
            return Utilities.IsBitSet((ushort) this.WSBoolOpt, (ushort) option);
        }

        public ExcelWorksheet InsertCopy(string destinationWorksheetName, ExcelWorksheet sourceWorksheet)
        {
            return this.parent.InsertCopyInternal(destinationWorksheetName, this.parent.IndexOf(this), sourceWorksheet);
        }

        public int InsertDataTable(DataTable dataTable, string startCell, bool columnHeaders)
        {
            int num;
            int num2;
            CellRange.PositionToRowColumn(startCell, out num, out num2);
            return this.InsertDataTable(dataTable, num, num2, columnHeaders);
        }

        public int InsertDataTable(DataTable dataTable, int startRow, int startColumn, bool columnHeaders)
        {
            int num2;
            int num3 = 0;
            if (columnHeaders)
            {
                num2 = 0;
                while (num2 < dataTable.Columns.Count)
                {
                    this.Cells[startRow, startColumn + num2].Value = dataTable.Columns[num2].ColumnName;
                    num2++;
                }
                num3++;
            }
            int num = 0;
            while (num < dataTable.Rows.Count)
            {
                for (num2 = 0; num2 < dataTable.Columns.Count; num2++)
                {
                    this.Cells[(startRow + num3) + num, startColumn + num2].Value = dataTable.Rows[num][num2];
                }
                num++;
            }
            return (num + num3);
        }

        public ExcelWorksheet InsertEmpty(string worksheetName)
        {
            return this.parent.InsertInternal(worksheetName, this.parent.IndexOf(this));
        }

        internal ExtractDataDelegateEventArgs OnWrongDataType(DataColumnMapping columnMapping, ExcelRow excelRow, DataTable dataTable, object excelCellValue)
        {
            ExtractDataDelegateEventArgs e = new ExtractDataDelegateEventArgs(ExtractDataError.WrongType, columnMapping, excelRow, dataTable, dataTable.Rows.Count, excelCellValue, null, ExtractDataEventAction.ThrowException);
            if (this.ExtractDataEvent != null)
            {
                this.ExtractDataEvent(null, e);
            }
            return e;
        }

        internal void SetWindowOption(bool val, WorksheetWindowOptions option)
        {
            this.windowOptions = (WorksheetWindowOptions) Utilities.SetBit((ushort) this.windowOptions, (ushort) option, val);
        }

        internal void SetWSBoolOption(bool val, WSBoolOptions option)
        {
            this.WSBoolOpt = (WSBoolOptions) Utilities.SetBit((ushort) this.WSBoolOpt, (ushort) option, val);
        }

        private static void ThrowInvalidDataException(int sourceRow, int sourceColumn, Exception inner)
        {
            throw new SpreadsheetException(string.Concat(new object[] { "Invalid data value when extracting to DataTable at SourceRowIndex: ", sourceRow, ", and SourceColumnIndex: ", sourceColumn, "." }), inner);
        }

        internal static bool ValueCanConvertToDataTableType(Type dataCellType, object excelValue)
        {
            if ((excelValue == null) || (excelValue == DBNull.Value))
            {
                return true;
            }
            Type type = excelValue.GetType();
            if (dataCellType == type)
            {
                return true;
            }
            if (!Utilities.IsNumericType(dataCellType) || !Utilities.IsNumericType(type))
            {
                return false;
            }
            double minValue = 0.0;
            double maxValue = 0.0;
            Utilities.GetMinimumAndMaximum(dataCellType, out minValue, out maxValue);
            double d = Convert.ToDouble(excelValue);
            if (d != Math.Floor(d))
            {
                return false;
            }
            return ((d <= maxValue) && (d >= minValue));
        }

        public CellRange Cells
        {
            get
            {
                if (this.cells == null)
                {
                    this.cells = new CellRange(this);
                }
                return this.cells;
            }
        }

        public ExcelColumnCollection Columns
        {
            get
            {
                return this.columns;
            }
        }

        public int DefaultColumnWidth
        {
            get
            {
                return this.defaultColumnWidth;
            }
            set
            {
                this.defaultColumnWidth = value;
            }
        }

        internal bool HasShape
        {
            get
            {
                return (this.Shapes.Count > 0);
            }
        }

        public HorizontalPageBreakCollection HorizontalPageBreaks
        {
            get
            {
                return this.horizontalPageBreaks;
            }
        }

        public SpreadsheetHyperlinkCollection Hyperlinks
        {
            get
            {
                return this.hyperlinks;
            }
        }

        internal MergedCellRanges MergedRanges
        {
            get
            {
                return this.mergedRanges;
            }
            set
            {
                this.mergedRanges = value;
            }
        }

        public string Name
        {
            get
            {
                return this.name;
            }
            set
            {
                this.parent.ExceptionIfNotUnique(value);
                this.name = value;
            }
        }

        public NamedRangeCollection NamedRanges
        {
            get
            {
                if (this.namedRanges == null)
                {
                    this.namedRanges = new NamedRangeCollection(this);
                }
                return this.namedRanges;
            }
        }

        internal ExcelWorksheetCollection Parent
        {
            get
            {
                return this.parent;
            }
        }

        internal ExcelFile ParentExcelFile
        {
            get
            {
                return this.Parent.Parent;
            }
        }

        public ExcelPictureCollection Pictures
        {
            get
            {
                return this.pictures;
            }
        }

        public ExcelPrintOptions PrintOptions
        {
            get
            {
                return this.printOptions;
            }
        }

        public bool Protected
        {
            get
            {
                return this.protectedWorksheet;
            }
            set
            {
                this.protectedWorksheet = value;
            }
        }

        public ExcelRowCollection Rows
        {
            get
            {
                return this.rows;
            }
        }

        internal ExcelShapeCollection Shapes
        {
            get
            {
                return this.shapes;
            }
        }

        public VerticalPageBreakCollection VerticalPageBreaks
        {
            get
            {
                return this.verticalPageBreaks;
            }
        }

        public ExcelViewOptions ViewOptions
        {
            get
            {
                return this.viewOptions;
            }
        }

        public delegate void ExtractDataEventHandler(object sender, ExtractDataDelegateEventArgs e);
    }
}
